<template>
  <div class="home">

    <div id="view"></div>
    <div id="scene_top">
      <h1>Mikutap</h1>
      <div id="ng">
        <p class="atten">十分抱歉<br>您的浏览器并不支持本页面需要的特性</p>
      </div>
      <div class="ok">
        <p id="bt_start"><a href="">!开始!</a></p>
      </div>
      <p id="bt_about"><a href="">*关于*</a></p>
      <div class="ok">
        <p class="attention">※请打开声音并享受。</p>
      </div>
      <div class="ok">
        <p class="tit"><strong>注意！搬运内容，原页面(Origin Site): <a href="https://aidn.jp/mikutap">https://aidn.jp/mikutap</a></strong></p>
      </div>
    </div>
    <div id="scene_loading">
      <hr size="1" color="#fff"> </div>
    <div id="scene_main" :class="showMainScene ? '':'main-sence-move'">

          <div class="error-message-bar">
            <div class="error-message-content" v-if="errorMsg">
                {{errorMsg}}
            </div>
          </div>

          <!-- 演奏模式选择框 -->
          <div class="play-mode-bar">
            <div class="play-mode-title">演奏模式：</div>
            <div v-for="item in playModeOption"
                 :class="['play-mode-btn', {'activeMode':item.key==currentPlayMode}]"
                 @click="changePlayMode(item.key)">
              {{item.value}}
            </div>
            <div>
              <img :src="LastSongIcon" class="song-switch-icon" @click="goLastSong">
              <img :src="NextSongIcon" class="song-switch-icon" @click="goNextSong">
            </div>
          </div>

          <!-- 曲谱信息框 -->
          <div class="song-info-bar" v-if="songLib[currentSongIdx]">
            <div style="padding-bottom: 10px;">当前乐谱：《{{songLib[currentSongIdx].name}}》</div>
            <div>歌手：{{songLib[currentSongIdx].singer}}</div>
          </div>

          <Piano></Piano>
<!--      <div class="set">-->
<!--        <p class="attention">点击 &amp; 拖动或者按任意键!</p>-->
<!--        <p id="bt_feedback"><a href="">反馈: 开启</a></p>-->
<!--        <p id="bt_backtrack"><a href="">背景音乐: 开启</a></p>-->
<!--        <div @click.prevent="goLastSong">cesi</div>-->
<!--      </div>-->

    </div>

    <div id="about_cover"></div>
<!--    <div id="bt_back">＜返回</div>-->
    <div id="bt_fs">□全屏显示</div>
    <div id="bt_hide" @click="hideMainScene">□隐藏其他</div>




<!--    <div class="error-message-bar">-->
<!--      <div class="error-message-content" v-if="errorMsg">-->
<!--          {{errorMsg}}-->
<!--      </div>-->
<!--    </div>-->

<!--    &lt;!&ndash; 演奏模式选择框 &ndash;&gt;-->
<!--    <div class="play-mode-bar">-->
<!--      <div class="play-mode-title">演奏模式：</div>-->
<!--      <div v-for="item in playModeOption"-->
<!--           :class="['play-mode-btn', {'activeMode':item.key==currentPlayMode}]"-->
<!--           @click="changePlayMode(item.key)">-->
<!--        {{item.value}}-->
<!--      </div>-->
<!--      <div>-->
<!--        <img :src="LastSongIcon" class="song-switch-icon" @click="goLastSong">-->
<!--        <img :src="NextSongIcon" class="song-switch-icon" @click="goNextSong">-->
<!--      </div>-->
<!--    </div>-->

<!--    &lt;!&ndash; 曲谱信息框 &ndash;&gt;-->
<!--    <div class="song-info-bar" v-if="songLib[currentSongIdx]">-->
<!--      <div style="padding-bottom: 10px;">当前乐谱：《{{songLib[currentSongIdx].name}}》</div>-->
<!--      <div>歌手：{{songLib[currentSongIdx].singer}}</div>-->
<!--    </div>-->

<!--    <Piano></Piano>-->
  </div>
</template>

<script>
import { queryPianoAudios,queryAllSongs } from "@/api/index";
import NextSongIcon from '@/assets/icon/nextSong.png';
import LastSongIcon from '@/assets/icon/lastSong.png';
import {PLAY_MODE} from "../config/constant"
import {notes} from '../utils/notes'
import Piano from '../components/instrument/Pinao';

export default {
  name: 'MainPage',
  component:{
    Piano
  },
  data(){
    return {
      songLib:[], // 存放后台曲库中所有乐谱
      song:[], // 存放单首歌曲的所有音阶
      currentSongIdx:0, // 当前演奏的乐谱序号
      musicLib:[], // 存放88键钢琴的所有音阶
      baseIdx: 3+12*2, // 首个C音符前面的所有键位数
      errorMsg:'', // 调用接口的报错信息
      currentPlayMode: 0, // 当前的演奏模式
      playModeOption:[], //可选择的演奏模式
      NextSongIcon,
      LastSongIcon,
      showMainScene:true, // 是否显示页面的操作菜单
    }
  },
  created(){
    this.initPlayMode();
    // 初始化88键钢琴的所有音阶
    this.initPianoAudios();
    // 初始化曲库
    this.initSongLib();
  },
  mounted(){
    document.body.addEventListener('keydown', e => {
      this.play(e.keyCode);
    });
  },
  methods:{
    initPianoAudios(){
      let that = this;
      queryPianoAudios().then(result => {
        if(result.responseCode == '200' && result.data.audios){
          that.musicLib = result.data.audios;
        }else{
          console.error('钢琴音乐文件初始化失败,读取本地文件',result.errorMsg);
          that.updateErrorMsg('钢琴音乐文件初始化失败,读取本地文件');
          that.initLocalPianoAudios();
        }
      }).catch(error => {
        console.log('error',error);
        console.error('钢琴音乐文件初始化失败,读取本地文件');
        that.initLocalPianoAudios();
      })
    },
    /**
     *  初始化乐谱库和首个乐谱序号
     */
    initSongLib(){
      let that = this;
      queryAllSongs().then(result => {
        if(result.responseCode == '200' && result.data.length > 0){
          that.songLib = result.data;
          let keyIdxForPiano = that.transferNoteToPianoKeyIdxArray(result.data[0].note);
          that.song = keyIdxForPiano;
          that.currentSongIdx = 0;
        }else{
          that.updateErrorMsg(result.errorMsg);
          console.error('曲库初始化失败',result.errorMsg);
        }
      }).catch(error => {
        console.log('error',error);
      })
    },

   /*
    * 初始化演奏模式
    */
    initPlayMode(){
      this.playModeOption = PLAY_MODE;
    },

    /**
     * 使用本地文件初始化88键钢琴的音乐文件
     */
    initLocalPianoAudios(){
      this.musicLib = notes;
    },
    /**
     *  功能描述：每个键盘事件对应的音乐代码
     *  1、若处于不循环模式，则单曲演奏完后不再补充乐谱
     *  2、若处于单曲循环模式，则单曲演奏完后自动补充同一首音乐的乐谱
     *  3、若处于列表循环模式，则单曲演奏完后自动补充列表中的下一首音乐
     *
     */
    play(keyCode){
      if(this.isMeetPlayCondition()){
        // 根据当前的演奏模式校验是否可以继续演奏
        if(this.song.length <= 0){
          if(this.currentPlayMode == PLAY_MODE[0].key){
            // 不循环
            this.updateErrorMsg('棒！你已经演奏完这首曲子了！')
          }else if(this.currentPlayMode == PLAY_MODE[1].key){
            // 单曲循环
            this.switchSong(this.currentSongIdx);
          }else{
            // 列表循环，若为列表中最后一首曲子，则回到第一首乐谱
            if(this.currentSongIdx == this.songLib.length-1){
              this.goFirstSong();
            }else{
              this.goNextSong();
            }
          }
        }
        const prefix = 'data:audio/mpeg;base64,';
        const keyboradIdx = this.song.shift();
        const hitNote = this.musicLib[keyboradIdx]
        let audio = new Audio(prefix + hitNote);
        audio.play();
      }else{
        this.updateErrorMsg('未满足演奏条件！请检查曲谱库和音源库！')
      }
    },
   /*
    * 检查是否满足演奏条件
    * 1、曲库内有数据
    * 2、音源库中有数据
    */
    isMeetPlayCondition(){
      let {songLib,musicLib} = this;
      let result = true;
      if(songLib.length <= 0){
        result = false;
      }
      if(musicLib.length <= 0){
        result = false;
      }
      return result;
    },

    /*
    *  将音阶字符串转换为88键钢琴对应的键位
    *  noteStr 音阶字符串，例如"1 1 5 5"
    */
    transferNoteToPianoKeyIdxArray(noteStr){
      let result = [];
      if(!noteStr){
        return result
      }
      // 得到音阶字符串中的所有音符
      let temNoteElementArr = noteStr.split(' ');
      temNoteElementArr.map(item =>{
        let keyPosition = this.transferSpectrumToKeyPosition(item);
        result.push(keyPosition);
      })
      return result;
    },
   /*
    * 切换到下一首音乐
    */
    goNextSong(){
      const nextSongIdx = this.currentSongIdx + 1;
      if(nextSongIdx >= this.songLib.length){
        this.updateErrorMsg('没有下一首了！');
        return;
      }
      this.switchSong(nextSongIdx);
    },
   /*
    * 切换到上一首音乐
    */
    goLastSong(){
      const lastSongIdx = this.currentSongIdx - 1;
      if(lastSongIdx < 0){
        this.updateErrorMsg('没有上一首了！');
        return;
      }
      this.switchSong(lastSongIdx);
    },
    /*
     * 切换到最后一首音乐
     */
    goTheLastSong(){
      if(this.songLib && this.songLib.length>0){
        this.switchSong(this.songLib.length-1)
        return;
      }
      this.updateErrorMsg('曲库空空如也，请补充曲谱');
    },
    /*
     * 切换到最后一首音乐
     */
    goFirstSong(){
      if(this.songLib && this.songLib.length>0){
        this.switchSong(0);
        return;
      }
      this.updateErrorMsg('曲库空空如也，请补充曲谱');
    },
    /**
     *  根据坐标索引切换乐谱
     */
    switchSong(songIdx){
      if(songIdx < 0){
        this.updateErrorMsg('不存在的歌曲索引');
        return
      }
      let songNote = this.songLib[songIdx].note;
      console.log('songNote',songNote)
      let keyIdxForPiano = this.transferNoteToPianoKeyIdxArray(songNote);
      console.log('keyIdxForPiano',keyIdxForPiano)
      this.song = keyIdxForPiano;
      this.currentSongIdx = songIdx;
    },
   /*
    * 修改演奏模式
    * 注意：点击时会刷新当前曲谱
    */
    changePlayMode(modeIdx){
      this.currentPlayMode = modeIdx
    },

   /*
    *  更新错误信息
    * errorMsg：错误信息的文本内容
    * showTime：提示信息框的停留时间，单位:毫秒值
    */
    updateErrorMsg(errorMsg,showTime){
      let that = this;
      this.errorMsg = errorMsg;
      showTime = showTime || 2000;
      // 定时清空错误信息文本框内容
      setTimeout(function () {
        that.errorMsg = '';
      }, showTime);
    },

    /**
     * 将简谱数值转为钢琴的键位
     * [1,7] 标识正常的C-B
     * [-1,-7] 表示降一个八度的C-B
     * [+1,+7] 表示升一个八度的C-B
     * 以此类推
     *
     * @param whiteNoteIndex 白键的键位
     * @returns {*}
     */
    transferSpectrumToKeyPosition(whiteNoteIndex){
      const upRegex = /\+/g;
      const downRegex = /\-/g;
      let upCycleNum = 0;
      if(whiteNoteIndex.match(upRegex)){
        upCycleNum = whiteNoteIndex.match(upRegex).length;
      }
      let downCycleNum =  0;
      if(whiteNoteIndex.match(downRegex)){
        downCycleNum = whiteNoteIndex.match(downRegex).length;
      }
      if(upCycleNum>0){
        let idxInGroup = parseInt(whiteNoteIndex.replaceAll(upRegex,''));
        let blackKeywordNum = this.getBlackKeywordNum(idxInGroup);
        return this.baseIdx + upCycleNum*12 + idxInGroup + blackKeywordNum;
      }else if(downCycleNum>0){
        let idxInGroup = parseInt(whiteNoteIndex.replaceAll(downRegex,''));
        let blackKeywordNum = this.getBlackKeywordNum(idxInGroup);
        return this.baseIdx - downCycleNum*12 + idxInGroup + blackKeywordNum;
      }else{
        let intIdx = parseInt(whiteNoteIndex);
        let blackKeywordNum = this.getBlackKeywordNum(intIdx);
        return this.baseIdx + intIdx + blackKeywordNum;
      }
    },
    getBlackKeywordNum(num){
      let result = 0;
      switch (num) {
        case 1:
          result = 0;
          break
        case 2:
          result = 1;
          break
        case 3:
          result = 2;
          break
        case 4:
          result = 2;
          break
        case 5:
          result = 3;
          break
        case 6:
          result = 4;
          break
        case 7:
          result = 5;
          break
      }
      return  result;
    },
    hideMainScene(){
      console.log('this.showMainScene',this.showMainScene)
      this.showMainScene = !this.showMainScene;
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.play-mode-bar{
  display: flex;
  justify-content: center;
  padding: 10px 30px;
  align-items: center;
  font-weight: 700;
}
.play-mode-btn{
  padding: 8px;
  background-color: #d3d3f3;
  margin-left: 10px;
  border-radius: 8px;
  font-size: 14px;
}
.activeMode{
  background-color: #d5ecb1;
  color: #048104;
}
.song-switch-icon{
  height: 50px;
  padding-left: 20px;
}
.error-message-bar{
  padding: 10px;
  display: flex;
  justify-content: center;
  height: 50px;
}
.error-message-content{
  background-color: #e2f2ff;
  width: 80%;
  padding: 10px 0px;
  border: 3px solid #1383e0;
  border-radius: 11px;
}
.song-info-bar{
  padding: 10px;
  font-size: 16px;
}
.main-sence-move{
  top: 5000px !important;
}

</style>
